package com.hj.springframework3.aop;

import com.hj.springframework3.context.ApplicationContextUtils;
import com.hj.springframework3.context.BeanDefinition;
import com.hj.springframework3.context.BeanPostProcessor;
import com.hj.springframework3.context.ConfigurableApplicationContext;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author : hujing
 * @Date: 2025/7/8 15:37
 * @Description:
 */
public abstract class AnnotationProxyBeanPostProcessor<A extends Annotation> implements BeanPostProcessor {

    Map<String,Object> originBeans = new HashMap<>();
    Class<A> annotationClass;
    
    public AnnotationProxyBeanPostProcessor(){
        this.annotationClass = getParameterizedType();
    }

    /**
     * 获取当前类的泛型参数类型
     * @return
     */
    private Class<A> getParameterizedType(){
        // 获取当前类的直接父类的泛型类型
        Type type = getClass().getGenericSuperclass();
        // 检查父类是否为参数化类型（即是否带泛型）
        if (!(type instanceof ParameterizedType)){
            throw new IllegalArgumentException("未找到泛型参数");
        }
        ParameterizedType pt = (ParameterizedType) type;
        // 从ParameterizedType对象中获取实际的泛型参数类型数组
        Type[] types = pt.getActualTypeArguments();
        if (types.length != 1){
            throw new IllegalArgumentException("泛型参数数量错误");
        }
        // 获取泛型参数数组中的第一个元素，即当前类的泛型参数类型
        Type r = types[0];
        if (!(r instanceof Class<?>)){
            throw new IllegalArgumentException("泛型参数类型错误");
        }
        return (Class<A>) r;
    }
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Class<?> beanClass = bean.getClass();
        // 判断类上是否有注解
        A anno = beanClass.getAnnotation(annotationClass);
        if (anno != null){
            String handlerName;
            try{
                handlerName = (String) anno.getClass().getMethod("value").invoke(anno);
            }catch (Exception e){
                throw new IllegalArgumentException("注解处理器名称获取失败");
            }
            Object proxy = createProxy(beanClass,bean,handlerName);
            originBeans.put(beanName,bean);
            return proxy;
        }else{
            return bean;
        }
    }
    
    Object createProxy(Class<?> beanClass,Object bean,String handlerName){
        ConfigurableApplicationContext ctx = (ConfigurableApplicationContext)ApplicationContextUtils.getRequiredApplicationContext();

        BeanDefinition def = ctx.findBeanDefinition(handlerName);
        if (def == null){
            throw new IllegalArgumentException("未找到处理器Bean定义");
        }
        Object handlerBean = def.getInstance();
        if (handlerBean == null){
            handlerBean = ctx.createBeanAsEarlySingleton(def);
        }
        if (handlerBean instanceof InvocationHandler handler){
            return ProxyResolver.getInstance().createProxy(bean,handler);
        }else{
            throw new IllegalArgumentException("处理器Bean类型错误");
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public Object postProcessOnSetProperty(Object bean, String beanName) {
        Object origin = this.originBeans.get(beanName);
        return origin != null ? origin : bean;
    }
}
